package queue;

import junit.framework.Assert;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * Classe de testes para uma fila circular implementada em array
 * @author Alexandre Bruno
 * @version 1.3
 */
public class TestQueue {

	int[] array1 = { 28, 65, 58, 43, 24, 9, 22, 13, 18, 21, 19, 11, 14, 17 };
				   // 0   1   2   3   4  5   6   7   8   9  10  11  12  13

	private Queue fila = new QueueImpl();

	@Before
	public void setUp() throws Exception {
	}

	@After
	public void tearDown() throws Exception {
	}

	/**
	 * Implementa os testes da classe inteira, chamando todos os metodos constantes na interface.
	 */
	@Test
	public void testClass() {
		// A ideia eh testar insercoes ate os limites, onde a fila levante excecoes
		// Estado atual: [__], __, __, __, __, __, __, __, __, __
		Assert.assertTrue(fila.isEmpty());
		Assert.assertEquals(0, fila.head());

		for (int i = 0; i < 10; i++) {
			try {
				fila.enqueue(array1[i]);
				Assert.assertFalse(fila.isEmpty());
			} catch (Queue.QueueOverflowException e) {
				Assert.assertEquals("Fila cheia", e.getMessage());
			}
		}

		Assert.assertTrue(fila.full());
		// Estado atual: [28], 65, 58, 43, 24, 9, 22, 13, 18, 21

		try {
			fila.enqueue(array1[10]);
		} catch (Queue.QueueOverflowException e) {
			Assert.assertEquals("Fila cheia", e.getMessage());
		}

		Assert.assertTrue(fila.full());
		Assert.assertEquals(0, fila.head()); 			// [28], 65, 58, 43, 24, 9, 22, 13, 18, 21

		/* Adicionando e removendo elementos sucessivas vezes */
		try {
			Assert.assertEquals(28, fila.dequeue()); 	// __, [65], 58, 43, 24, 9, 22, 13, 18, 21
			Assert.assertFalse(fila.full()); 			// __, [65], 58, 43, 24, 9, 22, 13, 18, 21
			Assert.assertEquals(1, fila.head()); 		// __, [65], 58, 43, 24, 9, 22, 13, 18, 21

			fila.enqueue(array1[11]); 					// 11, [65], 58, 43, 24, 9, 22, 13, 18, 21
			Assert.assertEquals(1, fila.head()); 		// 11, [65], 58, 43, 24, 9, 22, 13, 18, 21
			Assert.assertTrue(fila.full()); 			// 11, [65], 58, 43, 24, 9, 22, 13, 18, 21

			Assert.assertEquals(65, fila.dequeue()); 	// 11, __, [58], 43, 24, 9, 22, 13, 18, 21
			Assert.assertEquals(58, fila.dequeue()); 	// 11, __, __, [43], 24, 9, 22, 13, 18, 21
			fila.enqueue(array1[7]); 					// 11, 13, __, [43], 24, 9, 22, 13, 18, 21
			fila.enqueue(array1[12]);					// 11, 13, 14, [43], 24, 9, 22, 13, 18, 21

			Assert.assertEquals(3, fila.head()); 		// 11, 13, 14, [43], 24, 9, 22, 13, 18, 21
			Assert.assertEquals(43, fila.dequeue()); 	// 11, 13, 14, __, [24], 9, 22, 13, 18, 21
			Assert.assertEquals(4, fila.head()); 		// 11, 13, 14, __, [24], 9, 22, 13, 18, 21

			Assert.assertEquals(24, fila.dequeue()); 	// 11, 13, 14, __, __, [9], 22, 13, 18, 21
			Assert.assertFalse(fila.full());

			Assert.assertEquals(5, fila.head()); 		// 11, 13, 14, __, __, [9], 22, 13, 18, 21
			Assert.assertEquals(9, fila.dequeue()); 	// 11, 13, 14, __, __, __, [22], 13, 18, 21
			Assert.assertEquals(6, fila.head()); 		// 11, 13, 14, __, __, __, [22], 13, 18, 21
			Assert.assertEquals(22, fila.dequeue()); 	// 11, 13, 14, __, __, __, __, [13], 18, 21
			Assert.assertEquals(7, fila.head()); 		// 11, 13, 14, __, __, __, __, [13], 18, 21
			Assert.assertEquals(13, fila.dequeue()); 	// 11, 13, 14, __, __, __, __, __, [18], 21
			Assert.assertFalse(fila.full());

			Assert.assertEquals(18, fila.dequeue()); 	// 11, 13, 14, __, __, __, __, __, __, [21]
			Assert.assertEquals(21, fila.dequeue()); 	// [11], 13, 14, __, __, __, __, __, __, __
			Assert.assertEquals(11, fila.dequeue()); 	// __, [13], 14, __, __, __, __, __, __, __
			Assert.assertEquals(13, fila.dequeue()); 	// __, __, [14], __, __, __, __, __, __, __
			Assert.assertEquals(14, fila.dequeue()); 	// __, __, __, [__], __, __, __, __, __, __
			Assert.assertEquals(3, fila.head());
			Assert.assertTrue(fila.isEmpty());
			Assert.assertFalse(fila.full());

			fila.enqueue(array1[8]); 					// __, __, __, [18], __, __, __, __, __, __
			Assert.assertEquals(18, fila.dequeue()); 	// __, __, __, __, [__], __, __, __, __, __
			Assert.assertFalse(fila.full());
			Assert.assertEquals(4, fila.head());
			Assert.assertTrue(fila.isEmpty()); 			// __, __, __, __, [__], __, __, __, __, __

		} catch (Queue.QueueUnderflowException e) {
			Assert.assertEquals("Fila vazia", e.getMessage());
		} catch (Queue.QueueOverflowException e) {
			Assert.assertEquals("Fila cheia", e.getMessage());
		}

		try {
			fila.dequeue();
		} catch (Queue.QueueUnderflowException e) {
			Assert.assertEquals("Fila vazia", e.getMessage());
		}

		for (int i = 0; i < 10; i++) {
			try {
				fila.enqueue(array1[i + 3]);
			} catch (Queue.QueueOverflowException e) {
				Assert.assertEquals("Fila cheia", e.getMessage());
			}
		}
		
		Assert.assertTrue(fila.full());					// 43, 24, 9, 22, [13], 18, 21, 19, 11, 14
		Assert.assertFalse(fila.isEmpty());
		Assert.assertEquals(4, fila.head());
		
		try {
			fila.enqueue(array1[4]);
		} catch (Queue.QueueOverflowException e) {
			Assert.assertEquals("Fila cheia", e.getMessage());
		}
		
		Assert.assertTrue(fila.full());					// 43, 24, 9, 22, [13], 18, 21, 19, 11, 14
		Assert.assertFalse(fila.isEmpty());				
		Assert.assertEquals(4, fila.head());
		
		try {
			for (int i = 0; i < 10; i++) {
				fila.dequeue(); 						// __, __, __, __, [__], __, __, __, __, __
			}
		} catch (Queue.QueueUnderflowException e) {
			Assert.assertEquals("Fila vazia", e.getMessage());
		}
		
		Assert.assertTrue(fila.isEmpty());
		Assert.assertFalse(fila.full());
		Assert.assertEquals(4, fila.head());			// __, __, __, __, [__], __, __, __, __, __
		
	}
}
